/*!***************************************************
 * @file: func.c
 * @brief: 实现好友和通信功能的源文件
 * @author: ITHAO 
 * @date: 2018.12.11
 * @note: 
 ****************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>  

#include "func.h"
#include "list.h"
#include "debug.h"


static void init_friend_info(struct friend_info *info);
static bool mkdirs(const char  *pathname); 

/**
 * @brief   添加好友到好友链表
 * @param	friend_list_head--好友链表头
 *          info--好友信息
 * @return	TRUE            添加成功
 *          FAIL            添加失败
 */
bool add_friend_to_list(struct list_head *friend_list_head,
                       struct friend_info info)
{
    struct friend *p_friend = NULL;

    if (!friend_list_head) {
        DEBUG("PARAM NULL!\r\n");
        return FAIL;
    }
    if (strlen(info.name) == 0 || strlen(info.account) == 0) {
        DEBUG("PARAM NULL!\r\n");
        return FAIL;
    }

    p_friend = (struct friend *)malloc(sizeof(struct friend));
    init_friend_info(&p_friend->info);
    init_list_head(&p_friend->list);

    p_friend->info = info;
    list_add_tail(&p_friend->list, friend_list_head);

    return TRUE;
}


/**
 * @brief   从好友链表总删除好友        
 * @param	friend_list_head--好友链表头
 *          friend_account--好友账号
 * @return	
 *          TRUE         删除成功
 *          FAIL         不是好友
 */
bool remove_friend_from_list(struct list_head *friend_list_head,
                            char *friend_account)
{
    struct list_head *next, *head;
    struct friend *p_friend_tmp = NULL;
    int ret = 0;

    if (!friend_list_head || !friend_account) {
        DEBUG("PARAM ERROR!\n");
        return FAIL;
    }
    if (strlen(friend_account) == 0) {
        DEBUG("PARAM ERROR!\n");
        return FAIL;
    }

    ret = list_empty(friend_list_head);
    if (ret)
        return FAIL;

    head = friend_list_head;
    list_for_each(next, head) {
        p_friend_tmp = list_entry(next, struct friend, list);
        if (!strcmp(p_friend_tmp->info.account, friend_account)) {
            list_del(&p_friend_tmp->list);
            free(p_friend_tmp);
            return TRUE;
        }
    }

    return FAIL;
}


/**
 * @brief   清空好友链表       
 * @param	friend_list_head--好友链表头
 * @return	void
 */
void device_destroy_friend_list(struct list_head *friend_list_head)
{
    struct list_head *head, *next;
    struct friend *p_friend_tmp = NULL;

    if (!friend_list_head) {
        DEBUG("PARAM ERROR!\n");
        return;
    }

    head = friend_list_head;
    list_for_each(next, head) {
        p_friend_tmp = list_entry(next, struct friend, list);
        list_del(&p_friend_tmp->list);
        next = head;
        free(p_friend_tmp);
    }
}

/**
 * @brief   改变一个在好友链表的好友的网络状态      
 * @param	friend_account--好友账号
 *          status--想要改变的状态
 *          friend_list_head--好友链表头
 * @return	
 *          TRUE         改变成功
 *          FAIL         改变失败
 */
bool change_friend_online_flag(char *friend_account, bool status,
                                 struct list_head *friend_list_head)
{
    struct list_head *head, *next;
    struct friend *p_friend_tmp = NULL;

    if (!friend_list_head || !friend_account) {
        DEBUG("PARAM ERROR!\n");
        return FAIL;
    }
    if (strlen(friend_account) == 0) {
        DEBUG("PARAM ERROR!\n");
        return FAIL;
    }

    head = friend_list_head;
    list_for_each(next, head) {
        p_friend_tmp = list_entry(next, struct friend, list);
        if (!strcmp(p_friend_tmp->info.account, friend_account)) {
            p_friend_tmp->info.online_flag = status;
            return TRUE;
        }
    }

    return FAIL;
}

/**
 * @brief   初始化一个好友信息       
 * @param	info--好友的信息结构体指针
 * @return	
 */
static void init_friend_info(struct friend_info *info)
{
    if (!info)
        return;

    info->online_flag = 0;
    memset(info->name, '\0', NAME_MAX_LENGTH);
    memset(info->account, '\0', ACCOUNT_MAX_LENGTH);
}


/**
 * @brief	获取聊天记录
 * @param	p_chat_packet--聊天包
 *          聊天包里面需要有
 *          发送者账号--send_account
 *          接收者账号--recv_account
 * 
 * @param   packet_num--最近接收的第‘packet_num’条消息
 * @return	TRUE 有聊天信息并把聊天信息写入入口参数p_chat_packet里面
 *          FAIL 没有聊天信息
 * @note:   聊天记录保存目录是
 *                  /log/histroy/send_account/recv_account.txt
 */
bool get_chat_histroy(struct chat_packet *p_chat_packet, unsigned int packet_num)
{
    FILE *fp = NULL;
    int line = 0;
    char file_name[40];
    char dir_name[30];
    char send_name[NAME_MAX_LENGTH];
    char send_time[26];
    char msg[MSG_MAX_LENGTH];
    int how_much_packet;
    char transform[4];

    /*找到对应的聊天记录在那个文件*/
    strncpy(dir_name, CHAT_HISTROY_FILE, strlen(CHAT_HISTROY_FILE));
    strncpy(dir_name + strlen(CHAT_HISTROY_FILE),
                p_chat_packet->send_account, ACCOUNT_MAX_LENGTH);
    dir_name[strlen(dir_name)] = '/';
    strncpy(file_name, dir_name, 30);
    strncpy(file_name + strlen(file_name),
                p_chat_packet->recv_account, ACCOUNT_MAX_LENGTH);

    if (access(file_name, F_OK) != 0)
       return FAIL;
    
    fp = fopen(file_name, "rb+");
    
    fseek(fp, 0, SEEK_SET);
    fscanf(fp, "%s", transform);
    how_much_packet = atoi(transform);
    fseek(fp, 5, SEEK_SET);

    /*没有这么多聊天记录*/
    if (how_much_packet < packet_num) {
        p_chat_packet->send_name = NULL;
        p_chat_packet->send_time = NULL;
        p_chat_packet->msg = NULL;
        return FAIL;
    }

    line = (how_much_packet - packet_num + 1) * 3;
    while (line > 0) {
        fgets(send_name, NAME_MAX_LENGTH, fp);
        fgets(send_time, 26, fp);
        fgets(msg, MSG_MAX_LENGTH, fp);
        line = line - 3;
    }


    p_chat_packet->send_name = (char *)malloc(strlen(send_name) + 1);
    p_chat_packet->send_time = (char *)malloc(strlen(send_time) + 1);
    p_chat_packet->msg = (char *)malloc(strlen(msg) + 1);

    /*把换行符去掉*/
    send_name[strlen(send_name) - 1] = '\0';
    send_time[strlen(send_time) - 1] = '\0';
    msg[strlen(msg) - 1] = '\0';

    strcpy(p_chat_packet->send_name, send_name);
    strcpy(p_chat_packet->send_time, send_time);
    strcpy(p_chat_packet->msg, msg);

    fclose(fp);

    return TRUE;
}

/**
 * @brief	保存聊天记录
 * @param	chat_packet--聊天包
 *          sender_or_recver--0时发送者，1接收者
 * @return	void
 * @note:   聊天记录保存目录是
 *                  发送者
 *                  /log/histroy/send_account/recv_account.txt
 *                  接受者
 *                  /log/histroy/recv_account/send_account.txt
 */
void save_chat_history(struct chat_packet chat_packet, bool sender_or_recver)
{
    int ret = 0;
    FILE *fp = NULL;
    char file_name[40];
    char dir_name[30];
    int how_much_packet = 1;
    char transform[4] = {'1'};

    if (!chat_packet.send_name || !chat_packet.send_account ||
        !chat_packet.recv_account  || !chat_packet.send_time ||
        !chat_packet.msg) {
            DEBUG("PARAM NULL ERR\r\n");
            return;
        }

    memset(file_name, '\0', 40);
    memset(dir_name, '\0', 30);

    /*发送者*/
    if (sender_or_recver == 0){
        strncpy(dir_name, CHAT_HISTROY_FILE, strlen(CHAT_HISTROY_FILE));
        strncpy(dir_name + strlen(CHAT_HISTROY_FILE),
                chat_packet.send_account, ACCOUNT_MAX_LENGTH);
        dir_name[strlen(dir_name)] = '/';
        strncpy(file_name, dir_name, 30);
        strncpy(file_name + strlen(file_name),
                chat_packet.recv_account, ACCOUNT_MAX_LENGTH);
    /*接收者*/
    } else {
        strncpy(dir_name, CHAT_HISTROY_FILE, strlen(CHAT_HISTROY_FILE));
        strncpy(dir_name + strlen(CHAT_HISTROY_FILE),
                chat_packet.recv_account, ACCOUNT_MAX_LENGTH);
        dir_name[strlen(dir_name)] = '/';
        strncpy(file_name, dir_name, 30);
        strncpy(file_name + strlen(file_name),
                chat_packet.send_account, ACCOUNT_MAX_LENGTH);
    }

    if (access(dir_name, F_OK) != 0) {
        ret = mkdirs(dir_name);
        if (ret == FAIL) {
            DEBUG("Make chat histroy dir fail\r\n");
            return;
        }
    }
    
    fp = fopen(file_name, "rb+");
    
    if (fp == NULL) {
        fp = fopen(file_name, "wb+");
        snprintf(transform, sizeof(transform), "%d", how_much_packet);
        fseek(fp, 0, SEEK_SET);
        fwrite(transform, sizeof(transform), 1, fp);
        fprintf(fp, "%c", '\n');
        fseek(fp, 0, SEEK_END);
    } else {
        fseek(fp, 0, SEEK_SET);
        fscanf(fp, "%s", transform);
        how_much_packet = atoi(transform);
        how_much_packet = how_much_packet + 1;
        fseek(fp, 0, SEEK_SET);
        snprintf(transform, sizeof(transform), "%d", how_much_packet);
        fwrite(transform, sizeof(transform), 1, fp);
        fprintf(fp, "%c", '\n');
        fseek(fp, 0, SEEK_END);
    }

    fprintf(fp, "%s\n%s\n", chat_packet.send_name, chat_packet.send_time);
    fprintf(fp, "%s\n", chat_packet.msg);
    fclose(fp);
}

/**
 * @brief	创建多级目录  
 * @param	pathname--目录地址
 * @return	TRUE    创建成功
 *          FAIL    创建失败
 * @note:
 */
static bool mkdirs(const char  *pathname)  
{  
    char dirname[256];
    int count, len;

    strcpy(dirname, pathname);  
    len = strlen(dirname);  

    if(dirname[len-1] != '/')  
        strcat(dirname, "/");  
   
    len = strlen(dirname);  
   
    for(count = 1; count < len; count++)  
    {  
        if (dirname[count]=='/') {  
            dirname[count] = 0;  
            if(access(dirname, F_OK) !=0 ) {  
                if(mkdir(dirname, 0777) == -1) {   
                    perror("mkdir error");   
                    return FAIL;   
                }  
            }  
            dirname[count] = '/';  
        }  
    }  

    return TRUE;  
}

